/*
 * Copyright (C) 2008
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.googlecode.sca4idea.actions;

import com.intellij.openapi.project.Project;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.InputValidator;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.ide.actions.CreateElementActionBase;
import com.intellij.ide.fileTemplates.FileTemplateManager;
import com.intellij.ide.fileTemplates.FileTemplate;
import com.intellij.ide.fileTemplates.FileTemplateUtil;
import com.intellij.psi.*;
import com.intellij.util.IncorrectOperationException;
import com.googlecode.sca4idea.SCABundle;
import org.jetbrains.annotations.NotNull;

import java.util.Properties;

/**
 * Action for adding a new composite in the selected location.
 */
public class AddCompositeAction extends CreateElementActionBase {
    /**
     * Suffix applied to entered file names.
     */
    private static final String  COMPOSITE_SUFFIX = ".composite";

    private NewCompositeDialog newCompositeDialog = null;

    public AddCompositeAction() {
        super(SCABundle.message("new.menu.composite.text"), SCABundle.message("new.menu.composite.description"), null);
    }

    @NotNull
    protected PsiElement[] invokeDialog(Project project, PsiDirectory directory) {
        newCompositeDialog = new NewCompositeDialog(project);
        newCompositeDialog.show();
        try {
            if (newCompositeDialog.getExitCode() == DialogWrapper.OK_EXIT_CODE) {
                try {
                    String name = newCompositeDialog.getCompositeName();

                    checkBeforeCreate(name + COMPOSITE_SUFFIX, directory);
                    return create(name + COMPOSITE_SUFFIX, directory);
                } catch (Exception ex) {
                    Messages.showErrorDialog(directory.getProject(), getErrorTitle(), ex.getMessage());
                }
            }
        } finally {
            newCompositeDialog = null;
        }

        return new PsiElement[0];
    }

    protected void checkBeforeCreate(String s, PsiDirectory psiDirectory) throws IncorrectOperationException {
    }

    @NotNull
    protected PsiElement[] create(final String newName, final PsiDirectory directory) throws Exception {
        if (newCompositeDialog != null) {
            CompositeCreator creator = new CompositeCreator(directory, newName);
            ApplicationManager.getApplication().runWriteAction(creator);

            return creator.createdElements;
        }

        return new PsiElement[0];
    }

    protected String getDialogPrompt() {
        return SCABundle.message("new.composite.request");
    }

    protected String getErrorTitle() {
        return SCABundle.message("new.composite.error");
    }

    protected String getCommandName() {
        return SCABundle.message("new.composite.command");
    }

    protected String getActionName(PsiDirectory directory, String newName) {
        return SCABundle.message("new.composite.action.name", directory, newName);
    }

    protected class CompositeCreator implements Runnable {
        private PsiDirectory directory;
        private String newName;
        private PsiElement[] createdElements = new PsiElement[0];

        public CompositeCreator(PsiDirectory directory, String newName) {
            this.directory = directory;
            this.newName = newName;
        }

        public void run() {
            try {
                // Create the composite file
                FileTemplate template = FileTemplateManager.getInstance().getJ2eeTemplate("composite.xml");
                Properties props = new Properties();
                props.put("NAME", newCompositeDialog.getCompositeName());
                props.put("NAMESPACE", newCompositeDialog.getCompositeNamespace());
                props.put("AUTOWIRE", Boolean.toString(newCompositeDialog.getEnableAutowiring()).toLowerCase());
                PsiElement created = FileTemplateUtil.createFromTemplate(template, newName, props, directory);
                
                createdElements = new PsiElement[] { created };
            } catch (Exception ex) {
                 Messages.showErrorDialog(directory.getProject(), getErrorTitle(), ex.getMessage());
            }
        }
    }

    protected class NewValidator implements InputValidator {
        private PsiDirectory directory;
        private PsiElement[] createdFiles = new PsiElement[0];

        public NewValidator(PsiDirectory directory) {
            this.directory = directory;
        }

        public boolean checkInput(String text) {
            return true;
        }

        public boolean canClose(String text) {
            try {
                checkBeforeCreate(text + COMPOSITE_SUFFIX, directory);
                createdFiles = create(text + COMPOSITE_SUFFIX, directory);

                return true;
            } catch (Exception ex) {
                Messages.showErrorDialog(directory.getProject(), getErrorTitle(), ex.getMessage());
            }

            return false;
        }

        public PsiElement[] getCreatedFiles() {
            return createdFiles;
        }
    }
}
